package com.baselib.android.utils;


import org.apache.commons.lang.StringUtils;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by glx on 2016/9/12.
 */
public class TimeUtils {
    public static final Date ZERO_DATE = new Date(0);


    private static final SimpleDateFormat FORMAT_yyyyMMddHHmmss = new SimpleDateFormat("yyyyMMddHHmmss");
    private static final SimpleDateFormat FORMAT_yyyyMMddHHmm = new SimpleDateFormat("yyyyMMddHHmm");
    private static final SimpleDateFormat FORMAT_yyyyMMddHH = new SimpleDateFormat("yyyyMMddHH");
    private static final SimpleDateFormat FORMAT_yyyyMMdd = new SimpleDateFormat("yyyyMMdd");
    private static final SimpleDateFormat FORMAT_yyyy_MM_dd = new SimpleDateFormat("yyyy-MM-dd");
    private static final SimpleDateFormat FORMAT_yyyy_MM = new SimpleDateFormat("yyyy-MM");

    private static final SimpleDateFormat FORMAT_yyyyMM = new SimpleDateFormat("yyyyMM");
    private static final SimpleDateFormat FORMAT_yyyy = new SimpleDateFormat("yyyy");


    private static final SimpleDateFormat FORMAT_yyyy年MM月dd日HH时mm分ss秒SSS毫秒 = new SimpleDateFormat("yyyy年MM月dd日HH时mm分ss秒SSS毫秒");

    private static final SimpleDateFormat FORMAT_yyyy年MM月dd日HH时mm分ss秒 = new SimpleDateFormat("yyyy年MM月dd日HH时mm分ss秒");
    private static final SimpleDateFormat FORMAT_yyyy年MM月dd日HH时mm分 = new SimpleDateFormat("yyyy年MM月dd日HH时mm分");
    private static final SimpleDateFormat FORMAT_yyyy年MM月dd日HH时 = new SimpleDateFormat("yyyy年MM月dd日HH时");
    private static final SimpleDateFormat FORMAT_MM月dd日HH时 = new SimpleDateFormat("yyyy年MM月dd日HH时");
    private static final SimpleDateFormat FORMAT_yyyy年MM月dd日 = new SimpleDateFormat("yyyy年MM月dd日");
    private static final SimpleDateFormat FORMAT_yyyy年MM月 = new SimpleDateFormat("yyyy年MM月");
    private static final SimpleDateFormat FORMAT_yyyy年 = new SimpleDateFormat("yyyy年");
    private static final SimpleDateFormat FORMAT_MM月dd日 = new SimpleDateFormat("MM月dd日");


    private static final SimpleDateFormat FORMAT_DAY_TIME_SSS = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");

    private static final SimpleDateFormat FORMAT_DAY_1 = new SimpleDateFormat("yyyy-MM-dd");
    private static final SimpleDateFormat FORMAT_DAY_2 = new SimpleDateFormat("MM/dd/yyyy");
    private static final SimpleDateFormat FORMAT_DAY_3 = new SimpleDateFormat("yyyy-M-d");
    private static final SimpleDateFormat FORMAT_DAY_4 = new SimpleDateFormat("yyyy-MM-dd+HH:mm:ss");
    private static final SimpleDateFormat FORMAT_DAY_5 = new SimpleDateFormat("yyyy-MM-dd HH");
    private static final SimpleDateFormat FORMAT_DAY_6 = new SimpleDateFormat("yyyy-MM-dd HH:mm");
    private static final SimpleDateFormat FORMAT_DAY_7 = new SimpleDateFormat("yyyy/MM");
    private static final SimpleDateFormat FORMAT_DAY_8 = new SimpleDateFormat("MM/dd");
    private static final SimpleDateFormat FORMAT_DAY_9 = new SimpleDateFormat("dd");
    private static final SimpleDateFormat FORMAT_DAY_10 = new SimpleDateFormat("yyyy/MM/dd");

    private static final SimpleDateFormat FORMAT_DAY_TIME = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private static final SimpleDateFormat FORMAT_DAY_TIME_1 = new SimpleDateFormat("yyyy/MM/dd HH:mm");

    private static final SimpleDateFormat FORMAT_TIME = new SimpleDateFormat("HH:mm:ss");
    private static final SimpleDateFormat FORMAT_HHMM = new SimpleDateFormat("HH:mm");
    private static final SimpleDateFormat FORMAT_HH = new SimpleDateFormat("HH");


    public static String format_DAY_10(Date date) {
        if (date == null) {
            return null;
        }
        return FORMAT_DAY_10.format(date);
    }

    /**
     * 获取日期之前十三个月或者周的开始时间（周一）
     *
     * @param date
     * @param dateUnit
     * @return
     */
    public static List<Date> getPre13DateUnits(Date date, String dateUnit) {
        List<Date> lDate = new ArrayList<>();
        if (StringUtils.equals(dateUnit, "week")) {
            Date monday = TimeUtils.currentWeekBeginning(date);
            lDate.add(monday);
            for (; lDate.size() < 13; ) {
                monday = TimeUtils.preWeekBeginning(monday);
                lDate.add(monday);
            }
        } else if (StringUtils.equals(dateUnit, "mouth")) {
            Date monday = TimeUtils.currentMonthBeginning(date);
            lDate.add(monday);
            for (; lDate.size() < 13; ) {
                monday = TimeUtils.preMonthBeginning(monday);
                lDate.add(monday);
            }
        }

        lDate.sort(new Comparator<Date>() {
            @Override
            public int compare(Date o1, Date o2) {
                return o1.compareTo(o2);
            }
        });
        return lDate;
    }

    /**
     * 获取某段时这里写代码片间内的所有日期
     *
     * @param dBegin
     * @param dEnd
     * @return
     */
    public static List<Date> findDates(Date dBegin, Date dEnd) {
        List<Date> lDate = new ArrayList<>();
        lDate.add(dBegin);
        Calendar calBegin = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        calBegin.setTime(dBegin);
        // 测试此日期是否在指定日期之后
        while (dEnd.after(calBegin.getTime())) {
            // 根据日历的规则，为给定的日历字段添加或减去指定的时间量
            calBegin.add(Calendar.DAY_OF_MONTH, 1);
            lDate.add(calBegin.getTime());
        }
        return lDate;
    }

    public static Calendar getCalendar() {
        Calendar calendar = Calendar.getInstance();
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        return calendar;
    }

    /**
     * 获取当前日期是星期几<br>
     *
     * @param date
     * @return 当前日期是星期几
     */
    public static String getWeekOfDate(Date date) {
        String[] weekDays = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (w < 0)
            w = 0;
        return weekDays[w];
    }


    /**
     * 获取当前日期是星期几<br>
     *
     * @param date
     * @return 当前日期是星期几
     */
    public static Integer getWeekIndex(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (w < 0)
            w = 0;
        return w;
    }


    public static int toyyyyMMddInt(Date date) {
        return Integer.parseInt(format_yyyyMMdd(date));
    }

    public static String todayBeginning(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = getCalendar();
        calendar.setTime(date);

        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        return formatDayTime(calendar.getTime());
    }

    public static Date parseyyyy年MM月dd日(String t) {
        return parse(FORMAT_yyyy年MM月dd日, t);
    }

    public static Date parse(String t) {
        if (StringUtils.isEmpty(t)) {
            return null;
        }

        Date ret = parse(FORMAT_DAY_TIME, t);
        if (ret == null) {
            ret = parse(FORMAT_DAY_1, t);
        }
        if (ret == null) {
            ret = parse(FORMAT_HHMM, t);
        }
        if (ret == null) {
            ret = parse(FORMAT_DAY_2, t);
        }
        if (ret == null) {
            ret = parse(FORMAT_DAY_3, t);
        }
        if (ret == null) {
            ret = parse(FORMAT_yyyy_MM, t);
        }
        if (ret == null) {
            ret = parse(FORMAT_DAY_4, t);
        }
        if (ret == null) {
            ret = parse(FORMAT_DAY_5, t);
        }
        if (ret == null) {
            ret = parse(FORMAT_DAY_6, t);
        }

        if (ret == null) {
            ret = parse(FORMAT_yyyyMMddHHmmss, t);
        }
        if (ret == null) {
            ret = parse(FORMAT_yyyyMMddHHmm, t);
        }
        if (ret == null) {
            ret = parse(FORMAT_yyyyMMddHH, t);
        }
        if (ret == null) {
            ret = parse(FORMAT_yyyyMMdd, t);
        }
        if (ret == null) {
            ret = parse(FORMAT_yyyyMM, t);
        }

        if (ret == null) {
            ret = parse(FORMAT_yyyy年MM月dd日HH时mm分ss秒, t);
        }
        if (ret == null) {
            ret = parse(FORMAT_yyyy年MM月dd日HH时mm分, t);
        }
        if (ret == null) {
            ret = parse(FORMAT_yyyy年MM月dd日HH时, t);
        }
        if (ret == null) {
            ret = parse(FORMAT_yyyy年MM月dd日, t);
        }
        if (ret == null) {
            ret = parse(FORMAT_yyyy年MM月, t);
        }
        if (ret == null) {
            ret = parse(FORMAT_yyyy年, t);
        }
        if (ret == null) {
            ret = parse(FORMAT_DAY_TIME_SSS, t);
        }
        if (ret == null) {
            ret = parse(FORMAT_yyyy, t);
        }
        if (ret == null) {
            ret = parse(FORMAT_HH, t);
        }

        return ret;
    }


    public static int countAge(Date birthday) {
        /*从Calendar对象中或得一个Date对象*/
        Calendar cal = Calendar.getInstance();
        /*把出生日期放入Calendar类型的bir对象中，进行Calendar和Date类型进行转换*/
        Calendar bir = Calendar.getInstance();
        bir.setTime(birthday);
        /*如果生日大于当前日期，则抛出异常：出生日期不能大于当前日期*/
        if (cal.before(birthday)) {
            return -1;
        }
        /*取出当前年月日*/
        int yearNow = cal.get(Calendar.YEAR);
        int monthNow = cal.get(Calendar.MONTH);
        int dayNow = cal.get(Calendar.DAY_OF_MONTH);
        /*取出出生年月日*/
        int yearBirth = bir.get(Calendar.YEAR);
        int monthBirth = bir.get(Calendar.MONTH);
        int dayBirth = bir.get(Calendar.DAY_OF_MONTH);
        /*大概年龄是当前年减去出生年*/
        int age = yearNow - yearBirth;
        /*如果出当前月小与出生月，或者当前月等于出生月但是当前日小于出生日，那么年龄age就减一岁*/
        if (monthNow < monthBirth || (monthNow == monthBirth && dayNow < dayBirth)) {
            age--;
        }
        return age;
    }


    public static Date parse(SimpleDateFormat simpleDateFormat, String t) {
        if (StringUtils.isEmpty(t)) {
            return null;
        }

        try {
            return simpleDateFormat.parse(t);
        } catch (Exception e) {
            return null;
        }
    }

    public static String format_yyyyMMddHHmmss(Date date) {
        if (date == null) {
            return null;
        }
        return FORMAT_yyyyMMddHHmmss.format(date);
    }

    public static String format_DAY_TIME_1(Date date) {
        if (date == null) {
            return null;
        }
        return FORMAT_DAY_TIME_1.format(date);
    }

    public static String format_DAY_TIME_6(Date date) {
        if (date == null) {
            return null;
        }
        return FORMAT_DAY_6.format(date);
    }

    public static String format_HH(Date date) {
        if (date == null) {
            return null;
        }
        return FORMAT_HH.format(date);
    }

    public static String format_FORMAT_yyyy年MM月dd日HH时mm分ss秒SSS毫秒(Date date) {
        if (date == null) {
            return null;
        }
        return FORMAT_yyyy年MM月dd日HH时mm分ss秒SSS毫秒.format(date);
    }

    public static String format_FORMAT_DAY_TIME_SSS(Date date) {
        if (date == null) {
            return null;
        }
        return FORMAT_DAY_TIME_SSS.format(date);
    }

    public static String format_yyyyMMddHHmm(Date date) {
        if (date == null) {
            return null;
        }
        return FORMAT_yyyyMMddHHmm.format(date);
    }

    public static String format_yyyyMMddHH(Date date) {
        if (date == null) {
            return null;
        }
        return FORMAT_yyyyMMddHH.format(date);
    }

    public static String format_MM月dd日HH时(Date date) {
        if (date == null) {
            return null;
        }
        return FORMAT_MM月dd日HH时.format(date);
    }


    public static String format_yyyy_MM_dd(Date date) {
        if (date == null) {
            return null;
        }
        return FORMAT_yyyy_MM_dd.format(date);
    }

    public static String format_yyyy_MM(Date date) {
        if (date == null) {
            return null;
        }
        return FORMAT_yyyy_MM.format(date);
    }

    public static String format_yyyyMMdd(Date date) {
        if (date == null) {
            return null;
        }
        return FORMAT_yyyyMMdd.format(date);
    }

    public static String format_yyyyMM(Date date) {
        if (date == null) {
            return null;
        }
        return FORMAT_yyyyMM.format(date);
    }

    public static String format_yyyy(Date date) {
        if (date == null) {
            return null;
        }
        return FORMAT_yyyy.format(date);
    }


    public static String format_yyyy年MM月dd日HH时mm分ss秒(Date date) {
        if (date == null) {
            return null;
        }
        return FORMAT_yyyy年MM月dd日HH时mm分ss秒.format(date);
    }


    public static String format_yyyy年MM月dd日HH时mm分(Date date) {
        if (date == null) {
            return null;
        }
        return FORMAT_yyyy年MM月dd日HH时mm分.format(date);
    }

    public static String format_yyyyMMddHHmmMark(Date date) {
        if (date == null) {
            return null;
        }
        return FORMAT_DAY_6.format(date);
    }

    public static String format_yyyy年MM月dd日HH时(Date date) {
        if (date == null) {
            return null;
        }
        return FORMAT_yyyy年MM月dd日HH时.format(date);
    }

    public static String format_MM月dd日(Date date) {
        if (date == null) {
            return null;
        }
        return FORMAT_MM月dd日.format(date);
    }

    public static String format_yyyy年MM月dd日(Date date) {
        if (date == null) {
            return null;
        }
        return FORMAT_yyyy年MM月dd日.format(date);
    }

    public static String format_MMdd(Date date) {
        if (date == null) {
            return null;
        }
        return FORMAT_DAY_7.format(date);
    }

    public static String format_yyyMM(Date date) {
        if (date == null) {
            return null;
        }
        return FORMAT_DAY_7.format(date);
    }

    public static String format_dd(Date date) {
        if (date == null) {
            return null;
        }
        return FORMAT_DAY_9.format(date);
    }

    public static String format_yyyy年MM月(Date date) {
        if (date == null) {
            return null;
        }
        return FORMAT_yyyy年MM月.format(date);
    }

    public static String format_yyyy年(Date date) {
        if (date == null) {
            return null;
        }
        return FORMAT_yyyy年.format(date);
    }


    public static String formatDay(Date date) {
        if (date == null) {
            return null;
        }
        return FORMAT_DAY_1.format(date);
    }

    public static String formatDayTime(Date date) {
        if (date == null) {
            return null;
        }
        return FORMAT_DAY_TIME.format(date);
    }

    public static String formatTime(Date date) {
        if (date == null) {
            return null;
        }
        return FORMAT_TIME.format(date);
    }

    public static String formatHHMM(Date date) {
        if (date == null) {
            return null;
        }
        return FORMAT_HHMM.format(date);
    }

    public static Date nextMinuteBeginning(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = getCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE, 1);

        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        return calendar.getTime();
    }

    public static Date preMinuteBeginning(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = getCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE, -1);

        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();

    }

    public static Date currentMinuteBeginning(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = getCalendar();
        calendar.setTime(date);
        // calendar.add(Calendar.DATE, -1);

        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();

    }


    public static Date nextHourBeginning(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = getCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.HOUR_OF_DAY, 1);

        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        return calendar.getTime();
    }

    public static Date preHourBeginning(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = getCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.HOUR_OF_DAY, -1);

        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();

    }

    public static Date currentHourBeginning(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = getCalendar();
        calendar.setTime(date);

        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();

    }


    public static Date nextDayBeginning(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = getCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, 1);

        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        return calendar.getTime();
    }

    public static Date currentDayBeginning(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        return calendar.getTime();
    }

    public static Date preDayBeginning(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = getCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, -1);

        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();

    }


    public static Date nextWeekBeginning(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = getCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, 7);

        calendar.set(Calendar.DAY_OF_WEEK, 2);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }


    public static Date preWeekBeginning(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = getCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, -7);

        calendar.set(Calendar.DAY_OF_WEEK, 2);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date preWeek(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = getCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, -7);

        return calendar.getTime();
    }


    public static Date currentWeekBeginning(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = getCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, -7);

        calendar.set(Calendar.DAY_OF_WEEK, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 24);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }


    public static Date nextMonthBeginning(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = getCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, 1);

        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }


    public static Date preMonthBeginning(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = getCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, -1);

        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date preMonth(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = getCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, -1);
//
//        calendar.set(Calendar.DAY_OF_MONTH, 1);
//        calendar.set(Calendar.HOUR_OF_DAY, 0);
//        calendar.set(Calendar.MINUTE, 0);
//        calendar.set(Calendar.SECOND, 0);
//        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date currentMonthBeginning(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = getCalendar();
        calendar.setTime(date);
        // calendar.add(Calendar.MONTH, -1);

        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }


    public static Date nextYearBeginning(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = getCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.YEAR, 1);

        calendar.set(Calendar.DAY_OF_YEAR, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }


    public static Date preYearBeginning(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = getCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.YEAR, -1);

        calendar.set(Calendar.DAY_OF_YEAR, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date currentYearBeginning(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = getCalendar();
        calendar.setTime(date);
        //calendar.add(Calendar.YEAR, 2);

        calendar.set(Calendar.DAY_OF_YEAR, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }


    public static Date nextNMonth(Date date, int n) {
        if (date == null) {
            return null;
        }
        Calendar calendar = getCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, n);

        return calendar.getTime();
    }

    public static Date nextNMonthBegin(Date date, int n) {
        if (date == null) {
            return null;
        }
        return currentMonthBeginning(nextNMonth(date, n));
    }

    public static Date nextNDay(Date date, int n) {
        if (date == null) {
            return null;
        }
        Calendar calendar = getCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, n);

        return calendar.getTime();
    }


    public static Date lastNDay(Date date, int n) {
        if (date == null) {
            return null;
        }
        Calendar calendar = getCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.YEAR, -n);
        return calendar.getTime();
    }


    public static Date nextNHour(Date date, int n) {
        if (date == null) {
            return null;
        }
        Calendar calendar = getCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.HOUR, n);

        return calendar.getTime();
    }

    public static Date nextNMinute(Date date, int n) {
        if (date == null) {
            return null;
        }
        Calendar calendar = getCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE, n);

        return calendar.getTime();
    }


    public static Date nextNSecond(Date date, int n) {
        if (date == null) {
            return null;
        }
        Calendar calendar = getCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.SECOND, n);

        return calendar.getTime();
    }


    public static int getYearsFrom(Date from) {
        Date now = new Date();
        int userYear = now.getYear() - from.getYear();
        return userYear;
    }


    public static int getMonthsFrom(Date from) {
        Date now = new Date();
        int userYear = now.getYear() - from.getYear();
        int userMonth = userYear * 12 + (now.getMonth() - from.getMonth());
        return userMonth;
    }


    public static int getWeeksFrom(Date from) {
        Date now = new Date();

        Date w2 = TimeUtils.currentWeekBeginning(from);
        Date w1 = TimeUtils.currentWeekBeginning(now);

        return (int) ((w1.getTime() + 1 - w2.getTime()) / (1000L * 3600L * 24L * 7L));
    }

    public static int getDaysFrom(Date from) {
        Date now = new Date();

        Date d2 = TimeUtils.currentDayBeginning(from);
        Date d1 = TimeUtils.currentDayBeginning(now);
        return (int) ((d1.getTime() + 1 - d2.getTime()) / (1000L * 3600L * 24L));
    }


    public static int getYearsFrom(Date now, Date from) {
        int userYear = now.getYear() - from.getYear();
        return userYear;
    }


    public static int getMonthsFrom(Date now, Date from) {
        int userYear = now.getYear() - from.getYear();
        int userMonth = userYear * 12 + (now.getMonth() - from.getMonth());
        return userMonth;
    }


    public static int getWeeksFrom(Date now, Date from) {
        Date w2 = TimeUtils.currentWeekBeginning(from);
        Date w1 = TimeUtils.currentWeekBeginning(now);

        return (int) ((w1.getTime() + 1 - w2.getTime()) / (1000L * 3600L * 24L * 7L));
    }

    public static int getDaysFrom(Date now, Date from) {

        Date d2 = TimeUtils.currentDayBeginning(from);
        Date d1 = TimeUtils.currentDayBeginning(now);
        return (int) ((d1.getTime() + 1 - d2.getTime()) / (1000L * 3600L * 24L));
    }


    public static int getDayOfWeek_baseon_MondayIs1_SundayIs7(Date date) {
        int w = getCalendar().get(Calendar.DAY_OF_WEEK);
        switch (w) {
            case Calendar.MONDAY:
                return 1;
            case Calendar.TUESDAY:
                return 2;
            case Calendar.WEDNESDAY:
                return 3;
            case Calendar.THURSDAY:
                return 4;
            case Calendar.FRIDAY:
                return 5;
            case Calendar.SATURDAY:
                return 6;
            case Calendar.SUNDAY:
                return 7;
            default:
                throw new RuntimeException("未知day");
        }
    }


    private static void println(String str, Date date) {
        System.out.println(str + "    " + format_yyyy年MM月dd日HH时mm分ss秒(date));
    }

    public static void main(String[] args) {
        String dateStr = "2020-02-01 10:30:00";
        Date date = lastNDay(new Date(), 1);
//        System.out.println(TimeUtils.formatDay(TimeUtils.currentYearBeginning(date)));

        int allCount = 100;
        for (int i = 0; i < allCount; i++) {
            Date d = nextNDay(new Date(), i);
            int w = getWeekIndex(d);
            if (w != 0 && w != 6) {
                System.out.println(TimeUtils.formatDay(d));
            }
        }

//        Date nextB = nextDayBeginning(new Date());
//        println("nextDayBeginning", nextB);
//
//
//        Date preB = preDayBeginning(new Date());
//        println("preDayBeginning", preB);
//
//
//        Date nextWeekB = nextWeekBeginning(new Date());
//        println("nextWeekBeginning", nextWeekB);
//
//
//        Date preWeekB = preWeekBeginning(new Date());
//        println("preWeekBeginning", preWeekB);
//
//        Date preWeekE = currentWeekBeginning(new Date());
//        println("currentWeekBeginning", preWeekE);
//
//        Date nextMonthB = nextMonthBeginning(new Date());
//        println("nextMonthBeginning", nextMonthB);
//
//
//        Date preMonthB = preMonthBeginning(new Date());
//        println("preMonthBeginning", preMonthB);
//
//        Date preMonthE = currentMonthBeginning(new Date());
//        println("currentMonthBeginning", preMonthE);
//
//        Date nextYearB = nextYearBeginning(new Date());
//        println("nextYearBeginning", nextYearB);
//
//
//        Date preYearB = preYearBeginning(new Date());
//        println("preYearBeginning", preYearB);
//
//        Date preYearE = currentYearBeginning(new Date());
//        println("currentYearBeginning", preYearE);
//
//
//        println("pwe", TimeUtils.parse("2018-05-13 00:00:00"));
    }


    public static int getMothDays(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }


}
